﻿/*-----------------------------------------------
// File: BattleManager.cs 
// Description: 战场管理器 
// Author: Shaobing	492057342@qq.com
-----------------------------------------------*/
using UnityEngine;
using System.Collections;
using Battle.View;
using Battle.Engine;

namespace Battle
{
    public class BattleManager : MonoBehaviour
    {
        public BattleData battleData
        {
            get { return StaticData.curBattleData; }
        }
        public int attackerWaveNum;
        public int defenderWaveNum;
        public BattleViewCtrl battleViewCtrl = null;
        public EngineDefault battleEngine = null;
        //public LocalEngine battleEngine = null;//本地战斗引擎
        public BattlePanel battlePanel;

        public bool isPause;
        public static bool isBattleUI;
        public void Init()
        {
            attackerWaveNum = 0;
            defenderWaveNum = 0;
            if (battleData.battleType == BattleType.FIRST)
            {
                battleViewCtrl = gameObject.AddMissingComponent<BattleViewFirstCtrl>();
            }
            else {
                if (battleData.battleType == BattleType.PVE && StaticData.IsFirstChapter1_1_3())
                {
                    battleViewCtrl = gameObject.AddMissingComponent<CGuideBattleViewCtrl>();
                }
                else
                {
                    battleViewCtrl = gameObject.AddMissingComponent<BattleViewCtrl>();
                }
            }
            battleViewCtrl.Init(this);
            battleEngine = new EngineDefault();
            BattleMsgCtrl.GetInstance();
            this.enabled = true;
            if (!LoadingPanel.Instance.isLoading)
            {
                UIAutoSize.Instance.ShowMaskUI(false);
            }
            isBattleUI = true;
            balanceObj = null;
        }

        public bool IsFirstFight() {
            return battleData.battleType == BattleType.FIRST;
        }

        public void NewFight()
        {
#if UNITY_EDITOR && TEST100
            System.Collections.Generic.Dictionary<string, double[]> attActors = new System.Collections.Generic.Dictionary<string, double[]>();
            System.Collections.Generic.Dictionary<string, double[]> defActors = new System.Collections.Generic.Dictionary<string, double[]>();

            int winNum = 0;
            int loseNum = 0;

            long randomSeed = battleData.randomSeed;
            for (int i = 1; i <= 100; i++)
            {
                Battle.Engine.Debug.LogFightMsg100("\n_____battle num:" + i);
                battleData.randomSeed = Random.Range(1, 10000);
                EngineDefault battleEngineTest = new EngineDefault();
                var defender = battleData.GetFighter((int)BattleCamp.Defender, defenderWaveNum);
                var attacker = battleData.GetFighter((int)BattleCamp.Attacker, attackerWaveNum);
                Battle.Engine.InputData.InFightData data = Engine.InputData.InFightData.BuildInFightData(StaticData.curBattleData, attacker, defender);
                battleEngineTest.SetFightData(data);
                Engine.AI.EngineAI attackerAI = new Engine.AI.EnginePlayerAI();
                battleEngineTest.SetAI(CampType.ATTACK, attackerAI);
                Engine.AI.EngineAI defenderAI = new Engine.AI.EnginePlayerAI();
                battleEngineTest.SetAI(CampType.DEFENCE, defenderAI);
                battleEngineTest.Start();
                battleEngineTest.NextRound();
                battleEngineTest.Skip();
                EngineData edata = battleEngineTest.GetEngineData();
                Battle.Engine.Debug.LogFightMsg100("--camp:" + edata.attacker.camp);
                foreach (var a in edata.attacker.actors)
                {
                    bool flag = false;
                    foreach (var exa in attActors)
                    {
                        if (exa.Key.Equals(a.heroId + "_pos" + a.MainPosition.ToFPID()))
                        {
                            exa.Value[1] += a.exportDamHp;
                            exa.Value[2] += a.exportTreatHp;
                            flag = true;
                            break;
                        }
                    }
                    if (!flag)
                    {
                        double[] exports = { 0, 0, 0 };
                        exports[0] = a.MainPosition.ToFPID();
                        exports[1] = a.exportDamHp;
                        exports[2] = a.exportTreatHp;
                        attActors.Add(a.heroId + "_pos" + exports[0], exports);
                    }
                    Battle.Engine.Debug.LogFightMsg100("---actor: " + a.heroId + ", MaxHp:" + a.attribute.maxHp + ", exportDamHp:" + a.exportDamHp + ", exportTreatHp:" + a.exportTreatHp + ", position:" + a.MainPosition.ToFPID());
                }
                Battle.Engine.Debug.LogFightMsg100("--camp:" + edata.defender.camp);
                foreach (var a in edata.defender.actors)
                {
                    bool flag = false;
                    foreach (var exa in defActors)
                    {
                        if (exa.Key.Equals(a.heroId + "_pos" + a.MainPosition.ToFPID()))
                        {
                            exa.Value[1] += a.exportDamHp;
                            exa.Value[2] += a.exportTreatHp;
                            flag = true;
                            break;
                        }
                    }
                    if (!flag)
                    {
                        double[] exports = { 0, 0, 0 };
                        exports[0] = a.MainPosition.ToFPID();
                        exports[1] = a.exportDamHp;
                        exports[2] = a.exportTreatHp;
                        defActors.Add(a.heroId+"_pos"+exports[0], exports);
                    }
                    Battle.Engine.Debug.LogFightMsg100("---actor: " + a.heroId + ", MaxHp:" + a.attribute.maxHp + ", exportDamHp:" + a.exportDamHp + ", exportTreatHp:" + a.exportTreatHp + ", position:" + a.MainPosition.ToFPID());
                }

                if (edata.GetNumHP(CampType.DEFENCE) > 0)
                {
                    loseNum++;
                }
                else
                {
                    winNum++;
                }
            }

            Battle.Engine.Debug.LogFightMsg100("\n\n--camp: ATT");
            foreach (var exa in attActors)
            {
                Battle.Engine.Debug.LogFightMsg100("---actor: " + exa.Key + ", exportDamHp:" + exa.Value[1] + ", exportTreatHp:" + exa.Value[2]);
            }
            Battle.Engine.Debug.LogFightMsg100("\n--camp: DEF");
            foreach (var exa in defActors)
            {
                Battle.Engine.Debug.LogFightMsg100("---actor: " + exa.Key + ", exportDamHp:" + exa.Value[1] + ", exportTreatHp:" + exa.Value[2]);
            }
            
            Battle.Engine.Debug.LogFightMsg100("\n\n_____WIN:" + winNum);
            Battle.Engine.Debug.LogFightMsg100("_____LOSE:" + loseNum +"\n\n\n");

            battleData.randomSeed = randomSeed;
#endif
            Room.RoomModelPool.Instance.FlushCache();
            SetFightData();
            isSkip = false;
            battleViewCtrl.SwitchState(BattleState.ResourceLoadState);
        }

        public void FightOver()
        {
            if (battleViewCtrl.winCamp == BattleCamp.Attacker)
            {
                defenderWaveNum++;
            }
            else
            {
                attackerWaveNum++;
            }

            battleEngine.Stop();
            if (IsHaveNextFight())
            {
                NewFight();
            }
            else
            {
                BattleOver();
            }
        }

        public void BattleOver()
        {
            battleViewCtrl.SwitchState(BattleState.ResultState);
        }

        public void Unload()
        {
            battleViewCtrl.Unload();
            battlePanel.Hide();
            Destroy(battleViewCtrl);
            this.enabled = false;
            battleEngine = null;
            if (balanceObj != null)
            {
                GameObject.Destroy(balanceObj);
                balanceObj = null;
            }
        }

        public void Clear()
        {
            if (battleViewCtrl != null)
            {
                battleViewCtrl.StopAllCoroutines();
                battleViewCtrl.Clear();
            }
            battlePanel.Hide();
            StopAllCoroutines();
            if (balanceObj != null)
            {
                GameObject.Destroy(balanceObj);
                balanceObj = null;
            }
            this.enabled = false;
        }

        bool IsHaveNextFight()
        {
            var defender = battleData.GetFighter((int)BattleCamp.Defender, defenderWaveNum);
            var attacker = battleData.GetFighter((int)BattleCamp.Attacker, attackerWaveNum);
            if (defender == null || attacker == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        void SetFightData()
        {
            var defender = battleData.GetFighter((int)BattleCamp.Defender, defenderWaveNum);
            var attacker = battleData.GetFighter((int)BattleCamp.Attacker, attackerWaveNum);
            if (defender != null && attacker != null)
            {
                battleViewCtrl.InitBattleData(battleData.maxRound, attacker, defender);
                //Battle.Engine.InputData.InFightData data = Engine.InputData.InFightData.BuildInFightData(StaticData.curBattleData, attacker, defender);
                //battleEngine.SetFightData(data);

                //Engine.AI.EngineAI ai = new Engine.AI.EnginePlayerAI();
                //battleEngine.SetAI(CampType.DEFENCE, ai);

                //battleEngine.SetCallback(BattleMsgCtrl.GetInstance().engineCallBack);
                //battleEngine.Start();
            }

            SetFightEngineData();
        }

        void SetFightEngineData()
        {
            var defender = battleData.GetFighter((int)BattleCamp.Defender, defenderWaveNum);
            var attacker = battleData.GetFighter((int)BattleCamp.Attacker, attackerWaveNum);
            if (defender != null && attacker != null)
            {
                Battle.Engine.InputData.InFightData data = Engine.InputData.InFightData.BuildInFightData(StaticData.curBattleData, attacker, defender);
                battleEngine.SetFightData(data);
                if (battleData.battleType == BattleType.PVE || 
                    battleData.battleType == BattleType.WANTED || 
                    battleData.battleType == BattleType.RUSH || 
                    battleData.battleType == BattleType.RUSH_BOSS||
                    battleData.battleType == BattleType.FIELD_PVE ||
                    battleData.battleType == BattleType.FIELD_BOSS || 
                    battleData.battleType == BattleType.RECRUIT_SHOW ||
                    battleData.battleType == BattleType.ACTIVITY)
                {
                    if (battleData.isPlayBack)
                    {
                        Engine.AI.EnginePlaybackAI attackerAI = new Engine.AI.EnginePlaybackAI();
                        attackerAI.SetOperateRecord(battleData.operateRecord);
                        battleEngine.SetAI(CampType.ATTACK, attackerAI);
                    }
                    else
                    {
                        Engine.AI.EngineAI attackerAI = new Engine.AI.EnginePlayerAI();
                        battleEngine.SetAI(CampType.ATTACK, attackerAI);
                    }
                    Engine.AI.EngineAI defenderAI = new Engine.AI.EngineCopyEnemyAI();
                    battleEngine.SetAI(CampType.DEFENCE, defenderAI);
                }
                else if (battleData.battleType == BattleType.PVP || 
                    battleData.battleType == BattleType.FIELD_PVP || 
                    battleData.battleType == BattleType.FRIEND_PVP)
                {
                    Engine.AI.EngineAI attackerAI = new Engine.AI.EnginePlayerAI();
                    battleEngine.SetAI(CampType.ATTACK, attackerAI);
                    Engine.AI.EngineAI defenderAI = new Engine.AI.EnginePlayerAI();
                    battleEngine.SetAI(CampType.DEFENCE, defenderAI);
                }
                else if (battleData.battleType == BattleType.FIRST)
                {
                    Engine.AI.EngineAI attackerAI = new Engine.AI.EnginePlayerAI();
                    battleEngine.SetAI(CampType.ATTACK, attackerAI);
                    Engine.AI.EngineAI defenderAI = new Engine.AI.EngineCopyEnemyAI();
                    battleEngine.SetAI(CampType.DEFENCE, defenderAI);
                }
                else if (battleData.battleType == BattleType.BOSS_RAIDER) {
                    Engine.AI.EngineAI attackerAI = new Engine.AI.EnginePlayerAI();
                    battleEngine.SetAI(CampType.ATTACK, attackerAI);
                    Engine.AI.EngineAI defenderAI = new Engine.AI.EngineCopyEnemyAI();
                    battleEngine.SetAI(CampType.DEFENCE, defenderAI);
                }
                else
                {
                    Engine.AI.EngineAI attackerAI = new Engine.AI.EnginePlayerAI();
                    battleEngine.SetAI(CampType.ATTACK, attackerAI);
                    Engine.AI.EngineAI defenderAI = new Engine.AI.EnginePlayerAI();
                    battleEngine.SetAI(CampType.DEFENCE, defenderAI);
                }

                battleEngine.SetCallback(BattleMsgCtrl.GetInstance().engineCallBack);
                battleEngine.Start();
            }

        }

        public bool isSkip = false;

        public void Skip()
        {
            isSkip = true;
            battleEngine.Skip();
        }

        public BattleSpeed curSpeedEnum;

        public void ResetSpeed() {
            SetSpeed(BattleSpeed._1x);
        }
        public void SetSpeed(BattleSpeed e) {
            curSpeedEnum = e;
            switch (e) {
                case BattleSpeed._1x:
                    Time.timeScale = 1f;
                    break;
                case BattleSpeed._2x:
                    Time.timeScale = 2f;
                    break;
                default:
                    Time.timeScale = 1f;
                    break;
            }
        }

        /*
        public void Init()
        {
            battleViewCtrl = GetComponent<BattleViewCtrl>();
            battleViewCtrl.Init(this);
            battleEngine = new LocalEngine();
            battleEngine.Init(this);
            BattleMsgCtrl.GetInstance();
            this.enabled = true;
            isPause = false;
        }
        */

        void Update()
        {
            if (battleEngine != null)
                battleEngine.Update(Time.deltaTime);
            if (battleViewCtrl != null)
                battleViewCtrl.Tick();
            BattleMsgCtrl.GetInstance().Update();
        }

        public void InitBattleUI()
        {
            battlePanel.Init(battleViewCtrl);

        }

        public void ShowCopySmallBalance()
        {
            var obj = AssetLoad.ResourceManager.Instance.LoadResource("Pages/CopySmallBalance") as GameObject;
            if (obj != null)
            {
                var battleBalance = GameObject.Instantiate(obj) as GameObject;
                battleBalance.transform.SetParent(battlePanel.transform.parent);
                battleBalance.transform.localPosition = Vector3.zero;
                battleBalance.transform.localScale = Vector3.one;
                battleBalance.transform.localEulerAngles = Vector3.zero;
                battleBalance.GetComponent<CopySmallBalance>().Init();
                battleBalance.GetComponent<CopySmallBalance>().PlayAni();
            }
            else
            {
                UnityEngine.Debug.LogError("BattleManager ShowCopySmallBalance Error.");
                ManagerController.Instance.BattleToCopy();
            }
        }

        public void ShowCopyStoneBalance()
        {
            var obj = AssetLoad.ResourceManager.Instance.LoadResource("Pages/CopyStoneBalance") as GameObject;
            if (obj != null)
            {
                GameObject balance = GameObject.Instantiate(obj) as GameObject;
                balance.transform.SetParent(battlePanel.transform.parent);
                balance.transform.localPosition = Vector3.zero;
                balance.transform.localScale = Vector3.one;
                balance.transform.localEulerAngles = Vector3.zero;
                balance.GetComponent<CopyStoneBalance>().Init();
                balance.GetComponent<CopyStoneBalance>().Show();
            }
        }

        public void ShowBattleBalance(bool isWin, BattleType bt)
        {
            GameObject battleBalance = null;
            if (bt == BattleType.PVE || bt == BattleType.FIELD_PVE || bt == BattleType.FIELD_BOSS)
            {
                var obj = AssetLoad.ResourceManager.Instance.LoadResource("Pages/CopyBalance") as GameObject;
                if (obj != null)
                    battleBalance = GameObject.Instantiate(obj) as GameObject;
            }
            else if (bt == BattleType.WANTED)
            {
                var obj = AssetLoad.ResourceManager.Instance.LoadResource("Pages/WantedBalance") as GameObject;
                if (obj != null)
                    battleBalance = GameObject.Instantiate(obj) as GameObject;
            }
            else if (bt == BattleType.PVP)
            {
                var obj = AssetLoad.ResourceManager.Instance.LoadResource("Pages/PVPBattleBalance") as GameObject;
                if (obj != null)
                    battleBalance = GameObject.Instantiate(obj) as GameObject;
            }
            else if (bt == BattleType.PLUNDER)
            {
                var obj = AssetLoad.ResourceManager.Instance.LoadResource("Pages/CopyBalance") as GameObject;
                if (obj != null)
                    battleBalance = GameObject.Instantiate(obj) as GameObject;
            }
            else if (bt == BattleType.ACTIVITY)
            {
                var obj = AssetLoad.ResourceManager.Instance.LoadResource("Pages/CopyBalance") as GameObject;
                if (obj != null)
                    battleBalance = GameObject.Instantiate(obj) as GameObject;
            }
            else if (bt == BattleType.FRIEND_PVP)
            {
                var obj = AssetLoad.ResourceManager.Instance.LoadResource("Pages/FriendPVPBattleBalance") as GameObject;
                if (obj != null)
                    battleBalance = GameObject.Instantiate(obj) as GameObject;
            }
            else if (bt == BattleType.RUSH || bt == BattleType.RUSH_BOSS)
            {
                var obj = AssetLoad.ResourceManager.Instance.LoadResource("Pages/CopyBalance") as GameObject;
                if (obj != null)
                    battleBalance = GameObject.Instantiate(obj) as GameObject;
            }
            else if(bt == BattleType.FIELD_PVP)
            {
                var obj = AssetLoad.ResourceManager.Instance.LoadResource("Pages/FieldPVPBattleBalance") as GameObject;
                if (obj != null)
                    battleBalance = GameObject.Instantiate(obj) as GameObject;
            }

            balanceObj = battleBalance;
           
            if (battleBalance != null)
            {
                battleBalance.transform.SetParent(battlePanel.transform.parent);
                battleBalance.transform.localPosition = Vector3.zero;
                battleBalance.transform.localScale = Vector3.one;
                battleBalance.transform.localEulerAngles = Vector3.zero;
                battleBalance.GetComponent<BalanceBase>().Init(isWin ? BalanceResult.Win : BalanceResult.Lose);
                battleBalance.GetComponent<BalanceBase>().Show();
            }
            else
            {
                UnityEngine.Debug.LogError("BattleManager ShowBattleBalance Error.");
            }
        }

        GameObject balanceObj = null;


        #region Singlton
        private static BattleManager instance = null;
        void Awake()
        {
            instance = this;
        }
        public static BattleManager Instance
        {
            get
            {
                return instance;
            }
        }

        public static void Initialized()
        {
            Instance.Init();
        }
        #endregion

    }

}